﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ahp;

namespace AhpTest
{
    [TestClass]
    public class CriterionNodeTest
    {
        [TestMethod]
        public void GlobalPriorityTest()
        {
            CriterionNode singleCriterion = new CriterionNode();
            singleCriterion.LocalPriority = 0.153M;

            Assert.AreEqual(0.153M, singleCriterion.GlobalPriority);

            CriterionNode parentCriterion = new CriterionNode("parent", 0.122M);
            CriterionNode firstLevelSubcriterion = parentCriterion.SubcriterionNodes.Add("firstLevelSubcriterion", 0.345M);
            CriterionNode secondLevelSubcriterion = firstLevelSubcriterion.SubcriterionNodes.Add("secondLevelSubcriterion", 0.876M);

            Assert.AreEqual(0.122M * 0.345M * 0.876M, secondLevelSubcriterion.GlobalPriority);
        }

        [TestMethod]
        public void GoalNodeSetterTest()
        {
            //Initial goal setting
            CriterionNode criterionNode = new CriterionNode();
            GoalNode goalNode = new GoalNode();

            criterionNode.ParentCriterionNode = new CriterionNode();
            criterionNode.GoalNode = goalNode;

            Assert.AreEqual(goalNode, criterionNode.GoalNode);
            Assert.IsTrue(goalNode.CriterionNodes.Contains(criterionNode));
            Assert.IsNull(criterionNode.ParentCriterionNode);

            //Changing goal
            GoalNode newGoalNode = new GoalNode();
            criterionNode.GoalNode = newGoalNode;

            Assert.AreEqual(newGoalNode, criterionNode.GoalNode);
            Assert.IsFalse(goalNode.CriterionNodes.Contains(criterionNode));
            Assert.IsTrue(newGoalNode.CriterionNodes.Contains(criterionNode));

            //Setting null goal
            criterionNode.GoalNode = null;

            Assert.AreEqual(null, criterionNode.GoalNode);
            Assert.IsFalse(newGoalNode.CriterionNodes.Contains(criterionNode));
        }

        [TestMethod]
        public void ParentCriterionNodeSetterTest()
        {
            //Initial parent criterion node setting
            CriterionNode criterionNode = new CriterionNode();
            CriterionNode parentCriterionNode = new CriterionNode();

            criterionNode.GoalNode = new GoalNode();
            criterionNode.ParentCriterionNode = parentCriterionNode;

            Assert.AreEqual(parentCriterionNode, criterionNode.ParentCriterionNode);
            Assert.IsTrue(parentCriterionNode.SubcriterionNodes.Contains(criterionNode));
            Assert.IsNull(criterionNode.GoalNode);

            //Changing parent criterion node
            CriterionNode newParentCriterionNode = new CriterionNode();
            criterionNode.ParentCriterionNode = newParentCriterionNode;

            Assert.AreEqual(newParentCriterionNode, criterionNode.ParentCriterionNode);
            Assert.IsFalse(parentCriterionNode.SubcriterionNodes.Contains(criterionNode));
            Assert.IsTrue(newParentCriterionNode.SubcriterionNodes.Contains(criterionNode));

            //Setting null parent criterion node
            criterionNode.ParentCriterionNode = null;

            Assert.AreEqual(null, criterionNode.ParentCriterionNode);
            Assert.IsFalse(newParentCriterionNode.SubcriterionNodes.Contains(criterionNode));
        }

        #region Manipulations with subcriterions

        [TestMethod]
        public void AddCriterionNodeTest()
        {
            CriterionNode criterionNode = new CriterionNode("Criterion");
            criterionNode.AlternativeNodes.Add(new AlternativeNode(new Alternative("Alternative1")));
            criterionNode.AlternativeNodes.Add(new AlternativeNode(new Alternative("Alternative2")));
            CriterionNode subcriterionNode = new CriterionNode("Subcriterion");

            criterionNode.SubcriterionNodes.Add(subcriterionNode);
            Assert.AreEqual(criterionNode, subcriterionNode.ParentCriterionNode);
            Assert.AreEqual(0, criterionNode.AlternativeNodes.Count);
        }

        [TestMethod]
        public void RemoveCriterionNodeTest()
        {
            CriterionNode criterionNode = new CriterionNode();
            CriterionNode subcriterionNode = new CriterionNode();

            criterionNode.SubcriterionNodes.Add(subcriterionNode);
            Assert.AreEqual(criterionNode, subcriterionNode.ParentCriterionNode);

            criterionNode.SubcriterionNodes.Remove(subcriterionNode);
            Assert.IsNull(subcriterionNode.ParentCriterionNode);
        }

        [TestMethod]
        public void ClearCriterionNodesTest()
        {
            CriterionNode criterionNode = new CriterionNode("Criterion");
            CriterionNode subcriterionNode1 = new CriterionNode("Subcriterion1");
            CriterionNode subcriterionNode2 = new CriterionNode("Subcriterion2");
            criterionNode.SubcriterionNodes.Add(subcriterionNode1);
            criterionNode.SubcriterionNodes.Add(subcriterionNode2);

            criterionNode.SubcriterionNodes.Clear();
            Assert.IsNull(subcriterionNode1.ParentCriterionNode);
            Assert.IsNull(subcriterionNode2.ParentCriterionNode);
        }

        #endregion

        #region Manipulations with alternatives

        [TestMethod]
        public void AddAlternativeNodeTest()
        {
            CriterionNode criterionNode = new CriterionNode("Criterion");
            criterionNode.SubcriterionNodes.Add(new CriterionNode("Subcriterion1"));
            criterionNode.SubcriterionNodes.Add(new CriterionNode("Subcriterion2"));
            AlternativeNode alternativeNode = new AlternativeNode(new Alternative("Alternative"));

            criterionNode.AlternativeNodes.Add(alternativeNode);
            Assert.AreEqual(criterionNode, alternativeNode.CriterionNode);
            Assert.AreEqual(0, criterionNode.SubcriterionNodes.Count);
        }

        [TestMethod]
        public void RemoveAlternativeNodeTest()
        {
            CriterionNode criterionNode = new CriterionNode();
            AlternativeNode alternativeNode = new AlternativeNode(new Alternative());

            criterionNode.AlternativeNodes.Add(alternativeNode);
            Assert.AreEqual(criterionNode, alternativeNode.CriterionNode);

            criterionNode.AlternativeNodes.Remove(alternativeNode);
            Assert.IsNull(alternativeNode.CriterionNode);
        }

        [TestMethod]
        public void ClearAlternativeNodesTest()
        {
            CriterionNode criterionNode = new CriterionNode("Criterion");
            AlternativeNode alternativeNode1 = new AlternativeNode(new Alternative("Alternative1"));
            AlternativeNode alternativeNode2 = new AlternativeNode(new Alternative("Alternative2"));
            criterionNode.AlternativeNodes.Add(alternativeNode1);
            criterionNode.AlternativeNodes.Add(alternativeNode2);

            criterionNode.AlternativeNodes.Clear();
            Assert.IsNull(alternativeNode1.CriterionNode);
            Assert.IsNull(alternativeNode2.CriterionNode);
        }

        #endregion

        [TestMethod]
        public void HasSubcriterionNodesTest()
        {
            CriterionNode criterion = new CriterionNode();
            Assert.IsFalse(criterion.HasSubcriterionNodes);

            criterion.SubcriterionNodes.Add(new CriterionNode());
            Assert.IsTrue(criterion.HasSubcriterionNodes);

            criterion.SubcriterionNodes.Clear();
            Assert.IsFalse(criterion.HasSubcriterionNodes);
        }

        [TestMethod]
        public void HasAlternativeNodesTest()
        {
            CriterionNode criterion = new CriterionNode();
            Assert.IsFalse(criterion.HasAlternativeNodes);

            criterion.AlternativeNodes.Add(new AlternativeNode(new Alternative()));
            Assert.IsTrue(criterion.HasAlternativeNodes);

            criterion.AlternativeNodes.Clear();
            Assert.IsFalse(criterion.HasAlternativeNodes);
        }
    }
}
